package com.bruce.tool.web.filter.core;

import com.bruce.tool.common.exception.BaseRuntimeException;
import com.bruce.tool.common.util.SpringBeanUtils;
import com.bruce.tool.common.util.trace.TraceNoUtils;
import com.bruce.tool.web.filter.annotation.BlockWaiting;
import com.bruce.tool.web.filter.handler.LockHandler;
import com.bruce.tool.web.filter.util.RequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**防重复提交**/
@Slf4j
@SuppressWarnings("all")
public class WaitingHandlerInterceptor implements HandlerInterceptor{

    private static ThreadLocal<String> lockKey = new ThreadLocal<>();
    private static ThreadLocal<String> lockValue = new ThreadLocal<>();
    private final String prefix = "waiting";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod method = (HandlerMethod) handler;
        BlockWaiting blockWaiting = method.getMethodAnnotation(BlockWaiting.class);
        if (blockWaiting == null) {
            return true;
        }

        String token = RequestUtils.fetchToken(request);
        if(StringUtils.isBlank(token)){
            throw new BaseRuntimeException("ResubmitNotSupport", "请求等待提示,只支持get,postjson,postform");
        }
        token = this.prefix + token;
        String traceNo = TraceNoUtils.fetchTraceNo();
        lockKey.set(token);
        lockValue.set(traceNo);
        // 分布式锁
        LockHandler lockHandler = SpringBeanUtils.getBean(LockHandler.class);
        if(null == lockHandler){
            throw new BaseRuntimeException("ResubmitNotInit", "分布式锁未初始化,无法开启请求等待提示");
        }
        if (!lockHandler.lock(token, traceNo, 120)) {
            throw new BaseRuntimeException("BlockWaitingNotice", blockWaiting.message());
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if(!(handler instanceof HandlerMethod)){
            return;
        }
        HandlerMethod method = (HandlerMethod) handler;
        BlockWaiting forbidResubmit = method.getMethodAnnotation(BlockWaiting.class);
        if (forbidResubmit == null) { return; }
        // 分布式锁
        LockHandler lockHandler = SpringBeanUtils.getBean(LockHandler.class);
        lockHandler.unlock(lockKey.get(), lockValue.get());
        lockValue.remove();
        lockKey.remove();
    }

}
